#include "RelOp.h"
#include "old_Statistics.h"
#include "string.h"
#define RUN_LENGTH 10000

enum nodeType {selectpipe, selectfile, project, join, sum, groupby, distinct};

class QueryPlanNode
{
    public:
        nodeType type;
        QueryPlanNode* left;
        QueryPlanNode* right;
        Schema *node_out_sch;
        Pipe *out_pipe;
        virtual void Print(void) = 0;
        virtual void Execute(void) = 0;
        virtual void Wait(void) = 0;
        virtual void Clean(void) = 0;
        QueryPlanNode(nodeType);
        virtual ~QueryPlanNode() {}
};

class SelectFileNode : public QueryPlanNode
{
    public:
        int outPipeId;
        Pipe *outPipe;
        DBFile* file;
        char filename[1024];
        CNF* cnf;
        Record* literal;
        SelectFile sf;
        void Print();
        void Execute();
        void Wait();
        void Clean(void);
        SelectFileNode(DBFile* file, char *filename, int outPipeId, CNF* cnf, Record* literal, Pipe *outPipe);
};

class ProjectNode : public QueryPlanNode
{
    public:
        int inPipeId, outPipeId;
        Pipe *inPipe, *outPipe;
        vector<int> *keepMe;
        int *keepMeInt;
        int numAttsInput;
        int numAttsOutput;
        Project pro;
        void Print();
        void Execute();
        void Wait();
        void Clean(void);
        ProjectNode(int inPipeId, int outPipeId, vector<int> *keepMe, int numAttsInput, int numAttsOutput, Pipe *inPipe, Pipe *outPipe);
};

class JoinNode : public QueryPlanNode
{
    public:
        int inPipeIdL, inPipeIdR, outPipeId;
        Pipe *inPipeL, *inPipeR, *outPipe;
        CNF* cnf;
        Record* literal;
        Schema *schemaL, *schemaR;
        Join J;
        void Print();
        void Execute();
        void Wait();
        void Clean(void);
        JoinNode(int inPipeIdL, int inPipeIdR, int inPipeId, CNF* cnf, Record* literal, Schema *schemaL, Schema *schemaR, Pipe *inPipeL, Pipe *inPipeR, Pipe *outPipe);
};

class DistinctNode : public QueryPlanNode
{
    public:
        int inPipeId, outPipeId;
        Pipe *inPipe, *outPipe;
        Schema* schema;
        DuplicateRemoval dr;
        void Print();
        void Execute();
        void Wait();
        void Clean(void);
        DistinctNode(int inPipeId, int outPipeId, Schema* schema, Pipe *inPipe, Pipe *outPipe);
};

class SumNode : public QueryPlanNode
{
    public:
        int inPipeId, outPipeId;
        Pipe *inPipe, *outPipe;
        Function *computeMe;
        Sum sm;
        void Print();
        void Execute();
        void Wait();
        void Clean(void);
        SumNode(int inPipeId, int outPipeId, Function *computeMe, Pipe *inPipe, Pipe *outPipe);
};

class GroupByNode : public QueryPlanNode
{
    public:
        int inPipeId, outPipeId;
        Pipe *inPipe, *outPipe;
        OrderMaker *groupAtts;
        Function *computeMe;
        GroupBy gb;
        void Print();
        void Execute();
        void Wait();
        void Clean(void);
        GroupByNode(int inPipeId, int outPipeId, OrderMaker *groupAtts, Function *computeMe, Pipe *inPipe, Pipe *outPipe);
};
